package com.xique.park.service.biz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.xique.common.core.constant.UserConstants;
import com.xique.common.core.domain.R;
import com.xique.common.core.utils.OrikaUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.park.bean.domain.ParkInfo;
import com.xique.park.bean.domain.client.ParkClient;
import com.xique.park.bean.domain.client.ParkClientUser;
import com.xique.park.bean.domain.client.ParkClientUserInfo;
import com.xique.park.bean.request.client.ClientUserAddRequest;
import com.xique.park.bean.request.client.ClientUserEditRequest;
import com.xique.park.bean.request.client.ClientUserListRequest;
import com.xique.park.controller.client.web.bean.domain.Client;
import com.xique.park.controller.client.web.bean.domain.ClientUser;
import com.xique.park.controller.client.web.bean.domain.SysUser;
import com.xique.park.controller.client.web.service.service.IClientService;
import com.xique.park.controller.client.web.service.service.IClientUserService;
import com.xique.park.controller.client.web.service.service.ISysUserService;
import com.xique.park.service.biz.service.IParkClientUserBizService;
import com.xique.park.service.service.IParkClientUserInfoService;
import com.xique.park.service.service.IParkClientUserService;
import com.xique.park.service.service.IParkInfoService;
import com.xique.system.api.RemoteSystemUserService;
import com.xique.system.api.dto.SystemUserDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: caogq
 * @Date: 2021/7/21 11:51
 * @Description:
 */
@Service
public class ParkClientUserBizServiceImpl implements IParkClientUserBizService {

    @Autowired
    private IParkClientUserService parkClientUserService;

    @Autowired
    private IParkClientUserInfoService parkClientUserInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult saveParkClientUser(ParkClientUser parkClientUser) {
        List<String> parkClientIds = Arrays.asList(parkClientUser.getParkClients().split(","));
        //TODO 岗亭用户处理
//        parkClientUser.setPassword(new Md5Hash(parkClientUser.getLoginName() + parkClientUser.getPassword()).toHex());
        parkClientUser.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
        parkClientUser.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
        parkClientUser.setUpdateTime(new Date());
        //保存用户
        parkClientUserService.insertParkClientUser(parkClientUser);
        List<ParkClientUserInfo> parkClientUserInfos = new ArrayList<>();

        //保存岗亭和用户中间表
        parkClientIds.forEach(parkClientId -> parkClientUserInfos.add(new ParkClientUserInfo(Long.valueOf(parkClientId), parkClientUser.getId())));

        Boolean result = parkClientUserInfoService.batchInsertClientUserInfo(parkClientUserInfos);
        return result ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult updateParkClientUser(ParkClientUser newParkClientUser) {
        newParkClientUser.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
        newParkClientUser.setUpdateTime(new Date());
        String newParkClients = newParkClientUser.getParkClients();
        List<String> newClientIds = Arrays.asList(newParkClients.split(","));

        ParkClientUser oldParkClientUser = parkClientUserService.selectParkClientUserById(newParkClientUser.getId());
        List<Long> oldClientIds = oldParkClientUser.getParkClientList().stream().map(ParkClient::getId).collect(Collectors.toList());

        List<Long> deleteIds = oldClientIds.stream().filter(oldClientId -> !newClientIds.contains(oldClientId.toString())).collect(Collectors.toList());
        List<String> addIds = newClientIds.stream().filter(newClientId -> !oldClientIds.contains(Long.valueOf(newClientId))).collect(Collectors.toList());

        //用户基础信息修改
        parkClientUserService.updateParkClientUser(newParkClientUser);

        //删除中间表数据
        if (!deleteIds.isEmpty()) {
            List<ParkClientUserInfo> deleteList = new ArrayList<>();
            deleteIds.forEach(e -> deleteList.add(new ParkClientUserInfo(e, newParkClientUser.getId())));
            parkClientUserInfoService.batchDeleteParkClientUserInfo(deleteList);
        }
        //新增中间表数据
        if (!addIds.isEmpty()) {
            List<ParkClientUserInfo> addList = new ArrayList<>();
            addIds.forEach(e -> addList.add(new ParkClientUserInfo(Long.valueOf(e), newParkClientUser.getId())));
            parkClientUserInfoService.batchInsertClientUserInfo(addList);
        }


        return AjaxResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int deleteParkClientUserByIds(String ids) {
        List<String> idList = Arrays.asList(ids.split(","));
        idList.forEach(id -> parkClientUserInfoService.deleteParkClientUserInfoByUserId(Long.valueOf(id)));

        parkClientUserService.deleteParkClientUserByIds(ids);

        return 1;
    }

    /**
     * =================================================== 岗亭用户V1 ==================================================
     **/

    @Autowired
    private IClientUserService clientUserService;

    @Autowired
    private IClientService clientService;

    @Autowired
    private IParkInfoService parkInfoService;

    @Autowired
    private RemoteSystemUserService remoteSystemUserService;

    @Autowired
    private ISysUserService sysUserService;

    @Override
    public AjaxResult getClientUserList(ClientUserListRequest request) {

        Map<String, Object> map = new HashMap<>(2);
        map.put("list", new ArrayList<>());
        map.put("total", 0);

        List<ParkClientUser> list = parkClientUserService.selectParkClientUserListV1(request);
        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.success(map);
        }

        List<Long> userIds = list.stream().map(parkClientUser -> {
            // 赋值操作人
            String oldUpdateBy = parkClientUser.getUpdateBy();
            if (StrUtil.isNotBlank(oldUpdateBy)) {
                List<ParkClientUser> updateUser = parkClientUserService.selectParkClientUserByLoginName(oldUpdateBy);
                if (!updateUser.isEmpty()) {
                    parkClientUser.setUpdateBy(updateUser.get(0).getUserName());
                }
            }
            return parkClientUser.getId();
        }).collect(Collectors.toList());

        QueryWrapper<ClientUser> condition = new QueryWrapper<>();
        condition.in("sys_user_id", userIds);
        List<ClientUser> clientUserList = clientUserService.list(condition);
        List<Long> clientIds = clientUserList.stream().map(ClientUser::getClientId).collect(Collectors.toList());

        List<Client> clientList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(clientIds)) {
            clientList = clientService.selectClientByIds(clientIds);
        }
        Map<Long, Client> clientMap = clientList.stream().collect(Collectors.toMap(Client::getId, o -> o));

        Map<Long, List<ParkClient>> parkClientMap = new HashMap<>();
        clientUserList.forEach(item -> {
            List<ParkClient> parkClientList = parkClientMap.get(item.getSysUserId());
            if (StringUtils.isNull(parkClientList)) {
                parkClientList = new ArrayList<>();
            }
            if (StringUtils.isNotNull(clientMap.get(item.getClientId()))) {
                ParkClient parkClient = OrikaUtil.convert(clientMap.get(item.getClientId()), ParkClient.class);
                parkClientList.add(parkClient);
            }
            parkClientMap.put(item.getSysUserId(), parkClientList);
        });

        list.forEach(item -> {
            if (StringUtils.isNotNull(parkClientMap.get(item.getId()))) {
                item.setParkClientList(parkClientMap.get(item.getId()));
            }
        });

        map.put("list", list);
        map.put("total", new PageInfo(list).getTotal());

        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult addClientUser(ClientUserAddRequest request) {

        SysUser user = new SysUser();
        user.setParkId(request.getParkId());

        ParkInfo parkInfo = parkInfoService.selectParkInfoById(request.getParkId());
        user.setDeptId(parkInfo.getDeptId());
        user.setLoginName(request.getLoginName());
        user.setUserName(request.getUserName());
        user.setPhonenumber(request.getPhone());
        String platform = SecurityUtils.getPlatformType();
        if (UserConstants.Platform.ADMIN_SERVICE.equals(platform)) {
            user.setUserType(UserConstants.UserType.SERVICE_MANAGER);
        }
        if (UserConstants.Platform.ADMIN_PROJECT.equals(platform)) {
            user.setUserType(UserConstants.UserType.PROJECT_MANAGER);
        }
        user.setSex(request.getSex());
        user.setPassword(request.getPassword());
        user.setStatus(request.getStatus());
        user.setCarAuth(request.getCarAuth());
//        user.s

        R<Long> result = remoteSystemUserService.saveClientUser(OrikaUtil.convert(user, SystemUserDTO.class));
        if (R.FAIL == result.getCode()) {
            return AjaxResult.error(result.getMsg());
        }

        List<String> clientIds = Arrays.asList(request.getClientIds().split(","));
        List<ClientUser> clientUsers = new ArrayList<>(clientIds.size());
        clientIds.forEach(item -> {
            ClientUser clientUser = new ClientUser();
            clientUser.setClientId(Long.valueOf(item));
            clientUser.setSysUserId(result.getData());
            clientUsers.add(clientUser);
        });

        boolean isSuccess = clientUserService.saveBatch(clientUsers);
        if (!isSuccess) {
            return AjaxResult.error("绑定岗亭跟用户信息失败");
        }

        return AjaxResult.success("添加成功");
    }

    @Override
    public AjaxResult editClientUser(ClientUserEditRequest request) {

        QueryWrapper<SysUser> condition = new QueryWrapper<>();
        condition.eq("login_name", request.getLoginName());
        List<SysUser> list = sysUserService.list(condition);
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> userIds = list.stream().map(SysUser::getUserId).collect(Collectors.toList());
            userIds.remove(request.getUserId());
            if (CollectionUtils.isNotEmpty(userIds)) {
                return AjaxResult.error("账号已存在，请重新输入！");
            }
        }
        SysUser user = OrikaUtil.convert(request, SysUser.class, Collections.singletonMap("phone", "phonenumber"));
        user.setUpdateBy(SecurityUtils.getUsername());
        user.setUpdateTime(new Date());
        boolean isSuccess = sysUserService.updateById(user);
        if (!isSuccess) {
            return AjaxResult.error("编辑失败");
        }

        //TODO 更新岗亭跟用户的绑定关系
        ClientUser search = new ClientUser();
        search.setSysUserId(request.getUserId());
        List<ClientUser> clientUserList = clientUserService.selectClientUserList(search);
        List<Long> oldClientIds = clientUserList.stream().map(ClientUser::getClientId).distinct().collect(Collectors.toList());
        List<String> newClientIds = Arrays.asList(request.getClientIds().split(","));

        List<Long> deleteIds = oldClientIds.stream().filter(oldClientId -> !newClientIds.contains(oldClientId.toString())).collect(Collectors.toList());
        List<String> addIds = newClientIds.stream().filter(newClientId -> !oldClientIds.contains(Long.valueOf(newClientId))).collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(deleteIds)) {
            List<ClientUser> clientUsers = new ArrayList<>(deleteIds.size());
            deleteIds.forEach(item -> {
                ClientUser clientUser = new ClientUser();
                clientUser.setClientId(item);
                clientUser.setSysUserId(request.getUserId());
                clientUsers.add(clientUser);
            });
            clientUserService.deleteBatchClientUserList(clientUsers);
        }

        if (CollectionUtil.isNotEmpty(addIds)) {
            List<ClientUser> clientUsers = new ArrayList<>(addIds.size());
            addIds.forEach(item -> {
                ClientUser clientUser = new ClientUser();
                clientUser.setClientId(Long.valueOf(item));
                clientUser.setSysUserId(request.getUserId());
                clientUsers.add(clientUser);
            });
            clientUserService.saveBatch(clientUsers);
        }

        return AjaxResult.success("编辑成功");
    }

    @Override
    public AjaxResult getClientUserDetail(Long userId) {

        if (StringUtils.isNull(userId)) {
            return AjaxResult.error("用户id不能为空");
        }

        SysUser user = sysUserService.getById(userId);
        if (StringUtils.isNull(user)) {
            return AjaxResult.error("未找到对应用户");
        }

        Map<String, String> map = new HashMap<>(2);
        map.put("userId", "id");
        map.put("phonenumber", "phone");
        ParkClientUser parkClientUser = OrikaUtil.convert(user, ParkClientUser.class, map);

        QueryWrapper<ClientUser> clientUserQueryWrapper = new QueryWrapper<>();
        clientUserQueryWrapper.eq("sys_user_id", user.getUserId());
        List<ClientUser> clientUserList = clientUserService.list(clientUserQueryWrapper);
        if (CollectionUtils.isNotEmpty(clientUserList)) {
            List<Long> clientIds = clientUserList.stream().map(ClientUser::getClientId).distinct().collect(Collectors.toList());
            List<Client> clientList = clientService.selectClientByIds(clientIds);

            List<ParkClient> parkClientList = OrikaUtil.converts(clientList, ParkClient.class);

            parkClientUser.setParkClientList(parkClientList);
        }

        return AjaxResult.success(parkClientUser);
    }

    @Override
    public AjaxResult removeClientUser(Long userId) {

        if (StringUtils.isNull(userId)) {
            return AjaxResult.error("用户id不能为空");
        }

        QueryWrapper<SysUser> condition = new QueryWrapper<>();
        condition.eq("park_id", SecurityUtils.getParkId())
                .eq("user_id", userId);
        SysUser user = sysUserService.getOne(condition);
        if (StringUtils.isNull(user)) {
            return AjaxResult.error("未找到对应用户");
        }
        R<Boolean> result = remoteSystemUserService.removeClientUser(userId);
        if (R.FAIL == result.getCode()) {
            return AjaxResult.error(result.getMsg());
        }

        QueryWrapper<ClientUser> wrapper = new QueryWrapper<>();
        wrapper.eq("sys_user_id", userId);
        boolean isSuccess = clientUserService.remove(wrapper);
        if (!isSuccess) {
            return AjaxResult.error("删除岗亭跟用户关系失败");
        }

        return AjaxResult.success("删除成功");
    }

    @Override
    public AjaxResult resetClientUserPwd(Long userId) {

        if (StringUtils.isNull(userId)) {
            return AjaxResult.error("用户id不能为空");
        }

        QueryWrapper<SysUser> condition = new QueryWrapper<>();
        condition.eq("park_id", SecurityUtils.getParkId())
                .eq("user_id", userId);
        SysUser user = sysUserService.getOne(condition);
        if (StringUtils.isNull(user)) {
            return AjaxResult.error("未找到对应用户");
        }

        SysUser update = new SysUser();
        update.setUserId(userId);
        update.setPassword(SecurityUtils.encryptPassword("123456"));
        boolean isSuccess = sysUserService.updateById(update);
        if (!isSuccess) {
            return AjaxResult.error("重置密码失败");
        }

        return AjaxResult.success("重置密码为‘123456’成功！");
    }

    @Override
    public ParkClientUser getClientUserById(Long id) {
        SysUser sysUser = sysUserService.selectSysUserById(id);
        Map<String, String> map = new HashMap<>(2);
        map.put("userId", "id");
        map.put("phonenumber", "phone");
        return OrikaUtil.convert(sysUser, ParkClientUser.class, map);
    }
}
